import { BaseEntity } from "../common/entities/base.entity";
import { User } from "../user/user.entity";
import {
  Column,
  Entity,
  JoinColumn,
  ManyToOne,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  UpdateDateColumn,
  Index,
} from "typeorm";

/**
 * 日志级别枚举
 */
export enum LogLevel {
  ERROR = "error",
  WARN = "warn",
  INFO = "info",
  DEBUG = "debug",
  VERBOSE = "verbose",
}

/**
 * 日志类型枚举
 */
export enum LogType {
  HTTP = "http", // HTTP请求日志
  SYSTEM = "system", // 系统日志
  ERROR = "error", // 错误日志
  AUTH = "auth", // 认证日志
  DATABASE = "database", // 数据库操作日志
}

/**
 * 日志实体类 (Logs)
 *
 * 兼容Winston日志格式的综合日志系统，支持：
 * - Winston标准日志字段（level, message, context等）
 * - HTTP请求审计日志
 * - 错误日志和堆栈跟踪
 * - 用户操作审计
 * - 系统监控数据
 */
@Entity("logs")
@Index(["level", "logType", "createdAt"]) // 复合索引优化查询性能
@Index(["userId", "createdAt"]) // 用户日志查询索引
export class Logs extends BaseEntity {
  /**
   * 日志ID - 自增主键
   */
  @PrimaryGeneratedColumn()
  id: number;

  /**
   * 日志级别
   * 对应Winston的日志级别：error, warn, info, debug, verbose
   */
  @Column({
    type: "enum",
    enum: LogLevel,
    default: LogLevel.INFO,
    comment: "日志级别",
  })
  @Index() // 单独索引，用于按级别筛选
  level: LogLevel;

  /**
   * 日志类型
   * 区分不同类型的日志：HTTP请求、系统日志、错误日志等
   */
  @Column({
    type: "enum",
    enum: LogType,
    default: LogType.SYSTEM,
    comment: "日志类型",
  })
  @Index() // 单独索引，用于按类型筛选
  logType: LogType;

  /**
   * 日志消息
   * Winston的核心message字段，存储主要日志内容
   */
  @Column({
    type: "text",
    comment: "日志消息内容",
  })
  message: string;

  /**
   * 上下文信息
   * Winston的context字段，通常是模块名或功能名
   */
  @Column({
    type: "varchar",
    length: 100,
    nullable: true,
    comment: "日志上下文/模块名",
  })
  context?: string;

  /**
   * HTTP请求路径
   * 记录API端点或页面路径，如："/api/user/login"
   * 仅在logType为HTTP时使用
   */
  @Column({
    type: "varchar",
    length: 500,
    nullable: true,
    comment: "HTTP请求路径",
  })
  path?: string;

  /**
   * HTTP请求方法
   * 如：GET、POST、PUT、DELETE等
   * 仅在logType为HTTP时使用
   */
  @Column({
    type: "varchar",
    length: 10,
    nullable: true,
    comment: "HTTP请求方法",
  })
  method?: string;

  /**
   * HTTP状态码
   * HTTP响应状态码，如：200, 404, 500等
   * 仅在logType为HTTP时使用
   */
  @Column({
    type: "int",
    nullable: true,
    comment: "HTTP状态码",
  })
  statusCode?: number;

  /**
   * 请求/响应数据
   * 存储请求体或响应数据，通常为JSON字符串
   * 注意：敏感信息需要脱敏处理
   */
  @Column({
    type: "text",
    nullable: true,
    comment: "请求或响应数据",
  })
  data?: string;

  /**
   * 错误堆栈
   * Winston的stack字段，存储错误堆栈信息
   * 仅在level为error时使用
   */
  @Column({
    type: "text",
    nullable: true,
    comment: "错误堆栈信息",
  })
  stack?: string;

  /**
   * 元数据
   * Winston的meta字段，存储额外的结构化数据
   * JSON格式存储，如：用户代理、IP地址、请求ID等
   */
  @Column({
    type: "json",
    nullable: true,
    comment: "元数据信息",
  })
  meta?: Record<string, unknown>;

  /**
   * 操作结果状态码
   * 业务层面的结果状态：0-成功，非0-各种错误类型
   * 用于统计成功率和错误分析
   */
  @Column({
    type: "int",
    default: 0,
    comment: "操作结果状态码",
  })
  result: number;

  /**
   * 请求耗时（毫秒）
   * 记录请求处理时间，用于性能监控
   */
  @Column({
    type: "int",
    nullable: true,
    comment: "请求耗时(ms)",
  })
  duration?: number;

  /**
   * 客户端IP地址
   */
  @Column({
    type: "varchar",
    length: 45, // 支持IPv6
    nullable: true,
    comment: "客户端IP地址",
  })
  clientIp?: string;

  /**
   * 用户代理
   */
  @Column({
    type: "varchar",
    length: 500,
    nullable: true,
    comment: "用户代理信息",
  })
  userAgent?: string;

  /**
   * 关联用户 - 多对一关系
   * 记录是哪个用户执行的操作
   * 可为空，支持匿名操作日志
   */
  @ManyToOne(() => User, (user) => user.logs, {
    nullable: true,
    onDelete: "SET NULL", // 用户删除时保留日志但清空关联
  })
  @JoinColumn({ name: "userId" })
  user?: User;

  /**
   * 用户ID - 冗余字段
   * 便于查询和索引，避免每次都要JOIN用户表
   */
  @Column({
    type: "int",
    nullable: true,
    comment: "关联用户ID",
  })
  userId?: number;
}
